#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/poll.h>
#include <linux/interrupt.h>
#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#endif

#define GPIO_LOW 0
#define GPIO_HIGH 1
int beegpio;
/*
此处是探针程序的运行
*/
static irqreturn_t key_irq_handle(int irq, void *dev_id, struct pt_regs *regs)
{

        int i;
        printk("--hujiantong-devid-%s\n", &dev_id);
        for (i = 0; i < 10; i++)
        {
                printk("--hujiantong--%d\n", i);
                gpio_set_value(beegpio, GPIO_LOW);
                mdelay(50);
                gpio_set_value(beegpio, GPIO_HIGH);
                mdelay(200);
        }
        return IRQ_HANDLED;
}
static int samtu_ledtest_probe(struct platform_device *pdev)
{
        int ret = -1;
        int gpio, flag, irq;
        printk("-------hujiantong---------Enter %s\n", __FUNCTION__);

        struct device_node *bee_node = pdev->dev.of_node;

        printk("--------hujiantong-----------bee_node----------------------\n");
        printk("-----hujiantong-----%s-%d: enter\n", __FUNCTION__, __LINE__);
        //gpio = of_get_named_gpio_flags(bee_node,"ledgpiox",0,(enum of_gpio_flags *)&flag);//在DTS里面的gGPIO,想获取哪一个参数民

        beegpio = of_get_named_gpio_flags(bee_node, "beegpio", 0, &flag);
        if (!gpio_is_valid(beegpio))
        {
                printk("-----hujiantong-----this is valid invalid gpio\n");
                gpio_free(beegpio);
                return -1;
        }
        gpio_free(beegpio);
        ret = gpio_request(beegpio, "keygpio");
        if (ret != 0)
        {
                gpio_free(beegpio);
                printk("-----hujiantong-----this is invalid request gpio\n");
                return -EIO;
        }
        else
        {
                //gpio_direction_input(gpio);
                /*下面三个是根据不同的IO来设定不同的输出*/
                printk("-hujiantong--bee配置成功--\n");
        }

        gpio = of_get_named_gpio_flags(bee_node, "keygpio", 0, &flag);
        if (!gpio_is_valid(gpio))
        {
                printk("-----hujiantong-----this is valid invalid gpio\n");
                gpio_free(gpio);
                return -1;
        }
        gpio_free(gpio);
        ret = gpio_request(gpio, "keygpio");
        if (ret != 0)
        {
                gpio_free(gpio);
                printk("-----hujiantong-----this is invalid request gpio\n");
                return -EIO;
        }
        else
        {
                //gpio_direction_input(gpio);
                /*下面三个是根据不同的IO来设定不同的输出*/
                printk("-hujiantong--key--\n");
                printk("-hujiantong--%d--\n", gpio);
                printk("-----hujiantong-----%s-%d: exit\n", __FUNCTION__, __LINE__);

                irq = gpio_to_irq(gpio);                                                        //中断号映射
                ret = request_irq(irq, key_irq_handle, IRQF_TRIGGER_FALLING, "key", "keyflag"); // 注册中断
                if (ret < 0)
                {
                        printk("---hujiantong--irq--failed\n");
                        free_irq(irq, "keyflag");
                        gpio_free(gpio);
                        return ret;
                }
        }
        return 0; //return ok
}

static int samtu_ledtest_remove(struct platform_device *pdev)
{
        return 0;
}
#ifdef CONFIG_OF
/*
这个是match DTS相关的地方，.compatible 后面的字符和DTS一样就行
*/
static const struct of_device_id of_samtu_ledtest_match[] = {
    {.compatible = "samtu,bee"},
    {/*    */}};
#endif
/*
他首先执行的是.probe
主要的结构体，.probe 探针
             .remove 移除
             .driver 驱动
                 .name
                 .of_match_table  这个是match DTS相关的地方
*/
static struct platform_driver samtu_ledtest_driver =
    {
        .probe = samtu_ledtest_probe,
        .remove = samtu_ledtest_remove,
        .driver = {
            .name = "samtu_bee",
            .owner = THIS_MODULE,
#ifdef CONFIG_OF
            .of_match_table = of_samtu_ledtest_match,
#endif
        },

};

/*
下面的程序是驱动注册,注册平台驱的结构体，
static struct platform_driver samtu_ledtest_driver
*/
static int __init ledtest_init(void) //init led test //程序运行此处2
{
        printk(KERN_INFO "-----hujiantong-----Enter %s\n", __FUNCTION__);
        //platform_driver_register(&samtu_ledtest_driver);
        return platform_driver_register(&samtu_ledtest_driver); //然后由此进注册
        return 0;
}
/*
下面的程序是退出驱动注册

*/
static void __exit ledtest_exit(void) //exit the led test
{
        platform_driver_unregister(&samtu_ledtest_driver);
        printk("-----hujiantong-----Exit ledtest\n");
}

/*
下面的程序是驱动调用，整个驱动首先调用此处
*/
module_init(ledtest_init); //程序首先调用此处1
/*
下面的程序是驱动调用，整个驱动结束时调用此处
*/
module_exit(ledtest_exit);
